package com.spdb.oa;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.ws.Holder;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.spdb.oa.exception.OAException;
import com.spdb.oa.parser.OAXMLParserFactory;
import com.spdb.oa.type.Version;
import com.spdb.oa.type.OAServiceFunction;
import com.spdb.oa.type.Record;
import com.spdb.oa.type.SubmitForm;
import com.spdb.oa.type.SubmitFormWrapper;
import com.spdb.oa.type.Toolbar;
import com.spdb.oa.type.User;
import com.spdb.oa.type.UserListCount;
import com.spdb.oa.type.WFForm;
import com.spdb.oa.type.WorkflowOpinion;
import com.spdb.oa.util.OAConstants;
import com.spdb.oa.util.OAServiceUtil;

import sun.misc.BASE64Encoder;
import wspwsnamespace.WSPWS;
import wspwsnamespace.WSPWSSoap;

public class OAServiceImpl implements OAService {

	public static Logger logger = Logger.getLogger(OAServiceImpl.class
			.getName());
	public static Log log = LogFactory.getLog(OAServiceImpl.class);
	
	private String wsdlURL;
	private String namespaceURI;
	private String systemName;
	private String serviceName;
	private String userName;
	private String userNameBASE64Encoded;
	private String password;
	private String passwordBASE64Encoded;
	private String operationName;

	private WSPWS wspws;
	private WSPWSSoap wspwsSoap;

	private OAXMLParser parser;

	public OAServiceImpl() throws MalformedURLException, OAException {

		this(OAConstants.WSDLURL, OAConstants.NAMESPACEURI,
				OAConstants.SYSTEMNAME, OAConstants.SERVICENAME,
				OAConstants.USERNAME, OAConstants.PASSWORD,
				OAConstants.OPERATIONNAME, null);
	}

	public OAServiceImpl(String operationName) throws MalformedURLException,
			OAException {

		this(OAConstants.WSDLURL, OAConstants.NAMESPACEURI,
				OAConstants.SYSTEMNAME, OAConstants.SERVICENAME,
				OAConstants.USERNAME, OAConstants.PASSWORD, operationName, null);
	}

	/**
	 * init OAService,start WSPServic,and get soap binding
	 * 
	 * @param wsdlURL
	 * @param namespaceURI
	 * @param serviceName
	 * @param userName
	 * @param password
	 * @param operationName
	 * @throws MalformedURLException
	 */
	public OAServiceImpl(String wsdlURL, String namespaceURI,
			String systemName, String serviceName, String userName,
			String password, String operationName, OAXMLParser parser)
			throws MalformedURLException, OAException {
		super();
		this.wsdlURL = wsdlURL;
		this.namespaceURI = namespaceURI;
		this.systemName = systemName;
		this.serviceName = serviceName;
		this.userName = userName;
		this.password = password;
		this.operationName = operationName;

		BASE64Encoder encoder = new BASE64Encoder();
		this.userNameBASE64Encoded = encoder.encode(this.userName.getBytes());
		this.passwordBASE64Encoded = encoder.encode(this.password.getBytes());

		URL wsdlURL1 = new URL(this.wsdlURL);
		QName serviceName1 = new QName(this.namespaceURI, this.serviceName);

		WSPWS service = new WSPWS(wsdlURL1, serviceName1);
		WSPWSSoap soap = service.getWSPWSSoap();

		this.wspws = service;
		this.wspwsSoap = soap;

		try {
			if (parser == null) {
				this.parser = new OAXMLParser();
			} else {
				this.parser = parser;
			}
		} catch (ParserConfigurationException e) {
			throw new OAException(
					"A internal error: OAXMLParserConfigurationException");
		}

	}

	@Override
	public Map<User, UserListCount> getListCount() throws OAException {

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();
		String functionName = "GetListCount";
			
		String parameter = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Parameter version=\"1.0\"></Parameter>";

		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);
			logger.info(functionName + " return content: " + returnContent.value);
			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);
			return this.parser.parseGetListCount(returnContent.value);
		} catch (Exception e) {
			logger.info(functionName + " error: " + e.getMessage());

			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}		
		
/*		serviceInvocationHelper(parameter, "GetListCount",
				wspCredentialsResult, returnContent, resultCode, resultMessage);

		if (resultCode.value.equals("0")) {
			logger.log(Level.INFO, String.format("%s invocation failed: %s",
					"GetListCount", resultMessage.value));
			throw new OAException("Invocation of " + "GetListCount" + " failed");
		} else {
			try {
				return this.parser.parseGetListCount(returnContent.value);
			} catch (Exception e) {

				throw new OAException("Parse " + "GetListCount"
						+ " content error");
			}
		}*/

	}

	@Override
	public Map<User, List<Record>> getDBList(int pageSize, int currentPageNo)
			throws OAException {

		return getRecordList("GetDBList", pageSize, currentPageNo);

	}

	private Map<User, List<Record>> getRecordList(String functionName,
			int pageSize, int currentPageNo) throws OAException {
		String parameterTemplate = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Parameter version=\"1.0\"><PageSize><![CDATA[%d]]></PageSize>"
				+ "<CurrentPageNo><![CDATA[%d]]></CurrentPageNo></Parameter>";

		String parameter = String.format(parameterTemplate, new Integer(
				pageSize), new Integer(currentPageNo));

//		logger.info(functionName + " parameter: " + parameter);

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();
		
		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);
			logger.info(functionName + " return content: " + returnContent.value);
			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);
			return this.parser.parseFileList(returnContent.value);
		} catch (Exception e) {
			logger.info(functionName + " error: " + e.getMessage());

			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}
		
/*		long start = System.nanoTime();
			
		this.wspwsSoap.wspCredentials(this.userNameBASE64Encoded,
				this.passwordBASE64Encoded, this.systemName,
				this.operationName, functionName, parameter,
				wspCredentialsResult, returnContent, resultCode, resultMessage);
		
		long end = System.nanoTime();
		long timeCost = end - start;
		
		log.info(functionName + " Begin at: " + start + ", End at: " + end + ", Time cost: " + TimeUnit.NANOSECONDS.toMillis(timeCost) + "ms");
		
		// check result
		// 返回code待定
		if (resultCode.value.equals("0")) {
			logger.log(Level.INFO, String.format("%s invocation failed: %s",
					functionName, resultMessage.value));
			throw new OAException("Invocation of " + functionName + " failed: "
					+ resultMessage.value);
		} else {
			// call OAXMLParser to parse returnContent and return a Map<User,
			// List<Record>>
			try {
				return this.parser.parseDBList(returnContent.value);
			} catch (Exception e) {
				OAException oaException = new OAException("Parse "
						+ functionName + " content error: " + e.getMessage());
				oaException.oaMessage = resultMessage.value;
				throw oaException;
			}
		}*/
	}

	@Override
	public Map<User, List<Record>> getDYList(int pageSize, int currentPageNo) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<User, List<Record>> getCNList(int pageSize, int currentPageNo) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<User, List<Record>> getJBList(int pageSize, int currentPageNo)
			throws OAException {
		return getRecordList("GetJBList", pageSize, currentPageNo);
	}

	@Override
	public Toolbar getToolbar(String processId, String instanceId,
			String distributionId, String feedbackParameter) throws OAException {
		String parameterTemplate = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Parameter version=\"1.0\"><ProcessID><![CDATA[%s]]></ProcessID>"
				+ "<InstanceID><![CDATA[%s]]></InstanceID><DistributionID><![CDATA[%s]]></DistributionID>"
				+ "<FeedbackParameter><![CDATA[%s]]></FeedbackParameter></Parameter>";
		String parameter = String.format(parameterTemplate, processId,
				instanceId, "0", feedbackParameter);
		String functionName = "GetToolbar";
		
		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();

/*		logger.info("GetToolbar parameter: " + parameter);

		this.wspwsSoap.wspCredentials(this.userNameBASE64Encoded,
				this.passwordBASE64Encoded, this.systemName,
				this.operationName, "GetToolbar", parameter,
				wspCredentialsResult, returnContent, resultCode, resultMessage);

		// check result
		// 返回code待定
		try {
			if (resultCode.value.equals("0")) {
				logger.log(Level.INFO, String.format(
						"%s invocation failed: %s", "GetToolbar",
						resultMessage.value));
				throw new OAException("Invocation of " + "GetToolbar"
						+ " failed: " + resultMessage.value);
			} else {

				logger.info("Return Content: " + returnContent.value);
				return this.parser.parseGetToolbar(returnContent.value);
			}
		} catch (Exception e) {
			logger.info("GetToolbar parse ReturnContent error: "
					+ returnContent.value);

			OAException oaException = new OAException("Parse " + "GetToolbar"
					+ " content error: " + e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;

		}*/
		
		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);
			logger.info(functionName + " return content: " + returnContent.value);
			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);
			return this.parser.parseGetToolbar(returnContent.value);
		} catch (Exception e) {
			logger.info(functionName + " error: " + e.getMessage());

			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}

	}

	@Override
	public WFForm getWFForm(String processId, String instanceId,
			String distributionId, String feedbackParameter) throws OAException {
		String parameterTemplate = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Parameter version=\"1.0\"><ProcessID><![CDATA[%s]]></ProcessID>"
				+ "<InstanceID><![CDATA[%s]]></InstanceID><DistributionID><![CDATA[%s]]></DistributionID>"
				+ "<FeedbackParameter><![CDATA[%s]]></FeedbackParameter></Parameter>";
		String parameter = String.format(parameterTemplate, processId,
				instanceId, "0", feedbackParameter);
		String functionName = "GetWFForm";

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();

		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);
			logger.info("GetWFForm return content: " + returnContent.value);
			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);
			return this.parser.parseGetWFForm(returnContent.value);
		} catch (Exception e) {
			logger.info(functionName + " error: " + e.getMessage());

			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}

	}

	@Override
	public SubmitForm getSubmit(Version version, String processId, String instanceId,
			String distributionId, String feedbackParameter) throws OAException {
		String parameter = OAServiceUtil.buildParameter(version, processId,
																instanceId, distributionId, 
																feedbackParameter);
		String functionName = OAServiceFunction.GetSubmit.toString();

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();

		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);

			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);

			logger.info("Return Content: " + returnContent.value);
			return (SubmitForm) OAXMLParserFactory.getParserStrategy(functionName, version).parse(returnContent.value);
			
		} catch (Exception e) {
			logger.severe(functionName + " error: " + e.getMessage());
			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}

	}

	protected SubmitForm generateSubmitForm(String jsonStr) throws JsonParseException, JsonMappingException, IOException {
		ObjectMapper mapper = new ObjectMapper();
		SubmitFormWrapper sfWrapper = mapper.readValue(jsonStr, SubmitFormWrapper.class);
		return sfWrapper.SubmitForm;
	}
	
	@Override
	public JSONObject submitWF(String jsonStr) throws OAException {
		String parameter;
		try {
			/* This is the old way of converting json string to SubmitForm object
			 * 
			JsonFactory factory = new JsonFactory();
			JsonParser parser = factory.createParser(jsonStr);
			SubmitForm sf = SubmitForm.readFromJson(parser);
			SubmitFormBuilder builder = new SubmitFormBuilder(sf);
			parameter = builder.build();*/
			
			//Use the Jackson polymorph feature for converting json string of submitform to object
			SubmitForm sf = this.generateSubmitForm(jsonStr);
			SubmitFormBuilder builder = new SubmitFormBuilder(sf);
			parameter = builder.build();
			
		} catch (Exception e) {
			OAException ex =new OAException(e);
			throw ex;
		}

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();

		try {
			this.serviceInvocationHelper(parameter, "SubmitWF",
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);

			this.resultProcessHelper("SubmitWF", resultCode, resultMessage,
					returnContent);

			logger.info("SubmitWF Return Content: " + returnContent.value);

			return this.parser.parseSubmitWF(returnContent.value);
		} catch (Exception e) {
			logger.severe("SubmitWF" + " error: " + e.getMessage());
			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}
	}

	@Override
	public WorkflowOpinion getWorkFlowOpinion(String processId,
			String instanceId, String distributionId, String feedbackParameter)
			throws OAException {
		String parameter = String.format(OAConstants.PARAMETER_TEMPLATE,
				processId, instanceId, "0", feedbackParameter);
		String functionName = "GetWorkFlowOpinion";

		Holder<Boolean> wspCredentialsResult = new Holder<Boolean>();
		Holder<String> returnContent = new Holder<String>();
		Holder<String> resultCode = new Holder<String>();
		Holder<String> resultMessage = new Holder<String>();

		try {
			this.serviceInvocationHelper(parameter, functionName,
					wspCredentialsResult, returnContent, resultCode,
					resultMessage);

			this.resultProcessHelper(functionName, resultCode, resultMessage,
					returnContent);

			logger.info("Return Content: " + returnContent.value);

			return this.parser.parseGetWorkflowOpinion(returnContent.value);
		} catch (Exception e) {
			logger.severe(functionName + " error: " + e.getMessage());
			OAException oaException = new OAException(e.getMessage());
			oaException.oaMessage = resultMessage.value;
			throw oaException;
		}

	}

	private void serviceInvocationHelper(String parameter, String functionName,
			Holder<Boolean> wspCredentialsResult, Holder<String> returnContent,
			Holder<String> resultCode, Holder<String> resultMessage) {

		logger.info(functionName + " parameter: " + parameter);
		long start = System.nanoTime();
		
		this.wspwsSoap.wspCredentials(this.userNameBASE64Encoded,
				this.passwordBASE64Encoded, this.systemName,
				this.operationName, functionName, parameter,
				wspCredentialsResult, returnContent, resultCode, resultMessage);
		
		long end = System.nanoTime();
		long timeCost = end - start;
		
		log.info(functionName + " Begin at: " + start + ", End at: " + end + ", Time cost: " + TimeUnit.NANOSECONDS.toMillis(timeCost) + "ms");

	}

	private void resultProcessHelper(String functionName,
			Holder<String> resultCode, Holder<String> resultMessage,
			Holder<String> returnContent) throws OAException {
		if (resultCode.value.equals("0")) {
			logger.log(Level.INFO, String.format("%s invocation failed: %s",
					functionName, resultMessage.value));
			throw new OAException("Invocation of " + functionName + " failed: "
					+ resultMessage.value);
		}
	}

	public static void main(String[] args) throws MalformedURLException,
			OAException {
//		testGetDBJBList();
//		testGetToolbar();
		testGetListCount();
		testGetSubmit();
		testGetWorkflowOpinion();
		testGetWFForm();
	}

	public static WFForm testGetWFForm() throws OAException,
			MalformedURLException {
		OAServiceImpl s = new OAServiceImpl();
		String processId = "60962a9e-e422-4b6a-b784-828193e1926d";
		String instanceId = "5b542b03-ed1f-4bcd-b257-4dc07306e4c0";
		String feedbackParameter = "UHJvY2Vzc0lEPTYwOTYyYTllLWU0MjItNGI2YS1iNzg0LTgyODE5M2UxOTI2ZCZJbnN0YW5jZUlEPTViNTQyYjAzLWVkMWYtNGJjZC1iMjU3LTRkYzA3MzA2ZTRjMA==";

		WFForm wfForm = s.getWFForm(processId, instanceId, "0",
				feedbackParameter);

		System.out.println(wfForm);
		return wfForm;
	}

	public static void testGetWorkflowOpinion() throws OAException,
			MalformedURLException {
		OAServiceImpl s = new OAServiceImpl();
		String processId = "60962a9e-e422-4b6a-b784-828193e1926d";
		String instanceId = "5b542b03-ed1f-4bcd-b257-4dc07306e4c0";
		String feedbackParameter = "UHJvY2Vzc0lEPTYwOTYyYTllLWU0MjItNGI2YS1iNzg0LTgyODE5M2UxOTI2ZCZJbnN0YW5jZUlEPTViNTQyYjAzLWVkMWYtNGJjZC1iMjU3LTRkYzA3MzA2ZTRjMA==";

		WorkflowOpinion obj = s.getWorkFlowOpinion(processId, instanceId, "0",
				feedbackParameter);
		System.out.println(obj);
	}

	public static void testGetSubmit() throws OAException,
			MalformedURLException {
		OAServiceImpl s = new OAServiceImpl();

		// String processId = "cfcc5806-2a19-4965-ad85-4be67b43289d";
		// String instanceId = "4f7417bc-88ae-451a-8cb9-0f503f84886e";
		// String feedbackParameter =
		// "UHJvY2Vzc0lEPWNmY2M1ODA2LTJhMTktNDk2NS1hZDg1LTRiZTY3YjQzMjg5ZCZJbnN0YW5jZUlEPTRmNzQxN2JjLTg4YWUtNDUxYS04Y2I5LTBmNTAzZjg0ODg2ZSZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMyZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMw==";

		String processId = "29f9ab7c-061c-430f-a71e-d586fbe69c2f";
		String instanceId = "4eca4f20-884f-4637-8c83-dce052331ac4";
		String feedbackParameter = "UHJvY2Vzc0lEPTI5ZjlhYjdjLTA2MWMtNDMwZi1hNzFlLWQ1ODZmYmU2OWMyZiZJbnN0YW5jZUlEPTRlY2E0ZjIwLTg4NGYtNDYzNy04YzgzLWRjZTA1MjMzMWFjNCZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTk4Y2Q1NGMxLTdjOGUtNGQwOC05NTBhLWQ1OWY2MDk3ZjUyOCZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMyZNb2RlbEFsaWFzPU1vZGVsTFhEJlBhcmFtZXRlclNvdXJjZT1HZXRUb29sYmFy";

		SubmitForm sf = s.getSubmit(Version.OneDotZero, processId, instanceId, null,
				feedbackParameter);
		System.out.println(sf);

	}

	public static void testGetDBJBList() throws MalformedURLException,
			OAException {
		OAServiceImpl s = new OAServiceImpl();
		Map<User, List<Record>> map = s.getDBList(10, 1);
		System.out.println(map);
		map = s.getJBList(20, 1);
		System.out.println(map);

	}

	public static void testGetToolbar() throws MalformedURLException,
			OAException {
		OAServiceImpl s = new OAServiceImpl();

		// String processId = "99f88438-4197-4a70-9301-a89516522881";
		// String instanceId = "a6a27165-d829-4ad3-b63f-aa7491f33f61";
		// String feedbackParameter =
		// "UHJvY2Vzc0lEPTk5Zjg4NDM4LTQxOTctNGE3MC05MzAxLWE4OTUxNjUyMjg4MSZJbnN0YW5jZUlEPWE2YTI3MTY1LWQ4MjktNGFkMy1iNjNmLWFhNzQ5MWYzM2Y2MSZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTk4Y2Q1NGMxLTdjOGUtNGQwOC05NTBhLWQ1OWY2MDk3ZjUyOCZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMw==";

		// String processId = "cfcc5806-2a19-4965-ad85-4be67b43289d";
		// String instanceId = "4f7417bc-88ae-451a-8cb9-0f503f84886e";
		// String feedbackParameter =
		// "UHJvY2Vzc0lEPWNmY2M1ODA2LTJhMTktNDk2NS1hZDg1LTRiZTY3YjQzMjg5ZCZJbnN0YW5jZUlEPTRmNzQxN2JjLTg4YWUtNDUxYS04Y2I5LTBmNTAzZjg0ODg2ZSZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMyZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMw==";
		//
		String processId = "29f9ab7c-061c-430f-a71e-d586fbe69c2f";
		String instanceId = "4eca4f20-884f-4637-8c83-dce052331ac4";
		String feedbackParameter = "UGFyYW1ldGVyU291cmNlPUdldERCTGlzdCZQcm9jZXNzSUQ9MjlmOWFiN2MtMDYxYy00MzBmLWE3MWUtZDU4NmZiZTY5YzJmJkluc3RhbmNlSUQ9NGVjYTRmMjAtODg0Zi00NjM3LThjODMtZGNlMDUyMzMxYWM0Jk9wZXJhdGlvbj1EZWFsJkRhdGFUeXBlPURCJkV4ZWN1dG9ySUQ9OThjZDU0YzEtN2M4ZS00ZDA4LTk1MGEtZDU5ZjYwOTdmNTI4JmJlZGVsZWdhdG9ySWQ9JkxlYWRlcklEPSZVc2VySUQ9MmVkNGQzMGQtNDY2OS00OTQ4LTg2YzEtNGQxYWMwN2FkNGMzJk1vZGVsQWxpYXM9TW9kZWxMWEQ=";

		Toolbar toolbar = s.getToolbar(processId, instanceId, "0",
				feedbackParameter);
		System.out.println(toolbar);
	}

	public static void testGetListCount() throws MalformedURLException,
			OAException {
		OAServiceImpl s = new OAServiceImpl();
		Map<User, UserListCount> map = s.getListCount();
		System.out.println(map);
	}
}
